package socket

import (
	"card/app/framework/common"
	"encoding/json"
	"github.com/gorilla/websocket"
	"log"
	"sync"
	"time"
)

var (
	pongWait             = 10 * time.Second
	writeWait            = 10 * time.Second
	pingInterval         = (pongWait * 9) / 10
	maxMessageSize int64 = 1024
)

type Client struct {
	hub       *Hub
	conn      *websocket.Conn
	ReadChan  chan *Request
	WriteChan chan []byte
	sync.RWMutex
	pingTicker *time.Ticker
	Player     common.IPlayer
}

func NewClient(connect *websocket.Conn, hub *Hub) *Client {
	return &Client{
		hub:        hub,
		conn:       connect,
		ReadChan:   hub.ClientReadChan,
		WriteChan:  make(chan []byte, 1024),
		pingTicker: nil,
	}
}

func (c *Client) Close() error {
	return c.conn.Close()
}
func (c *Client) Send(buf []byte) error {
	c.WriteChan <- buf
	return nil
}

func (c *Client) Run() {
	go c.Write()
	go c.Read()
}
func (c *Client) Read() {
	defer func() {
		c.hub.removeClient(c)
	}()
	c.conn.SetReadLimit(maxMessageSize)
	c.conn.SetReadDeadline(time.Now().Add(pongWait))
	c.conn.SetPongHandler(func(data string) error {
		log.Println("receive pong", data)
		c.conn.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})
	for {
		messageType, message, err := c.conn.ReadMessage()
		log.Println(messageType, string(message))
		if err != nil {
			break
		}
		var data Request
		err = json.Unmarshal(message, &data)
		if err != nil {
			break
		}
		//客户端发来的消息是二进制消息
		if messageType == websocket.TextMessage {
			if c.ReadChan != nil {
				c.ReadChan <- &Request{
					Data:   data.Data,
					Route:  data.Route,
					Type:   data.Type,
					Id:     data.Id,
					Client: c,
				}
			}
		} else {

		}
	}
}
func (c *Client) Write() {
	defer func() {
		c.pingTicker.Stop()
		c.hub.removeClient(c)
	}()
	c.pingTicker = time.NewTicker(pingInterval)
	for {
		select {
		case <-c.pingTicker.C:
			c.conn.SetWriteDeadline(time.Now().Add(writeWait))
			err := c.conn.WriteMessage(websocket.PingMessage, nil)
			if err != nil {
				log.Println("ping error:", err)
				return
			}
		case message, ok := <-c.WriteChan:
			c.conn.SetWriteDeadline(time.Now().Add(writeWait))
			if !ok {
				c.conn.WriteMessage(websocket.CloseMessage, nil)
				return
			}
			err := c.conn.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				return
			}
		}
	}
}
